﻿package core.image
{
    import flash.geom.*;

    public class ChannelCurve extends Object
    {
        public var LUT:Array;
        public var spline:Spline3;
        public var channelShift:uint;
        public var points:Array;
        public var splineVals:Array;
        public var histogram:Array;
        private var width:uint = 256;
        private var height:uint = 256;

        public function ChannelCurve(param1:uint)
        {
            this.channelShift = param1;
            this.points = new Array();
            this.LUT = new Array(256);
            this.splineVals = new Array(256);
            this.histogram = new Array(256);
            this.points.push(new Point(0, 255));
            this.points.push(new Point(255, 0));
            this.Update();
            return;
        }// end function

        public function Preset(push:Array) : void
        {
            var _loc_2:int = 0;
            this.points = new Array();
            while (_loc_2 < push.length)
            {
                
                this.points.push(new Point(push[_loc_2], push[(_loc_2 + 1)]));
                _loc_2 = _loc_2 + 2;
            }
            this.Update();
            return;
        }// end function

        public function Update() : void
        {
            var _loc_1:int = 0;
            var _loc_2:int = 0;
            var _loc_4:int = 0;
            var _loc_3:* = 256;
            this.spline = new Spline3();
            while (_loc_4 < this.points.length)
            {
                
                this.spline.addControlPoint(this.points[_loc_4].x, this.points[_loc_4].y);
                _loc_3 = Math.min(_loc_3, this.points[_loc_4].x);
                _loc_2 = Math.max(_loc_2, this.points[_loc_4].x);
                _loc_4++;
            }
            if (_loc_3 < 0)
            {
                _loc_3 = 0;
            }
            if (_loc_2 > 255)
            {
                _loc_2 = 255;
            }
            _loc_1 = Math.round(this.spline.eval(_loc_3));
            _loc_4 = 0;
            while (_loc_4 < _loc_3)
            {
                
                this.splineVals[_loc_4] = _loc_1;
                this.LUT[_loc_4] = 255 - _loc_1 << this.channelShift;
                _loc_4++;
            }
            _loc_4 = _loc_3;
            while (_loc_4 < (_loc_2 + 1))
            {
                
                _loc_1 = Math.min(Math.max(0, Math.round(this.spline.eval(_loc_4))), 255);
                this.splineVals[_loc_4] = _loc_1;
                this.LUT[_loc_4] = 255 - _loc_1 << this.channelShift;
                _loc_4++;
            }
            _loc_4 = _loc_2 + 1;
            while (_loc_4 < 256)
            {
                
                this.splineVals[_loc_4] = _loc_1;
                this.LUT[_loc_4] = 255 - _loc_1 << this.channelShift;
                _loc_4++;
            }
            return;
        }// end function

        public function removePoint(push:int) : void
        {
            this.points.splice(push, 1);
            return;
        }// end function

        public function addPoint(push:Point) : void
        {
            if (push.x > this.points[0].x && push.x < this.points[(this.points.length - 1)].x)
            {
                this.points.push(push);
                this.points.sortOn("x", Array.NUMERIC);
            }
            return;
        }// end function

        public function euclideanDistance2D(addControlPoint:Point, addControlPoint:Point) : Number
        {
            var _loc_3:* = addControlPoint.x - addControlPoint.x;
            var _loc_4:* = addControlPoint.y - addControlPoint.y;
            return Math.sqrt(_loc_3 * _loc_3 + _loc_4 * _loc_4);
        }// end function

        public function sqrEuclideanDistance2D(addControlPoint:Point, addControlPoint:Point) : Number
        {
            var _loc_3:* = addControlPoint.x - addControlPoint.x;
            var _loc_4:* = addControlPoint.y - addControlPoint.y;
            return _loc_3 * _loc_3 + _loc_4 * _loc_4;
        }// end function

        public function findClosestControlPoint(_local1:Point, _local1:int) : int
        {
            var _loc_3:Number = NaN;
            var _loc_4:int = 0;
            var _loc_5:* = Number.MAX_VALUE;
            var _loc_6:* = -1;
            while (_loc_4 < this.points.length)
            {
                
                _loc_3 = this.euclideanDistance2D(_local1, this.points[_loc_4]);
                if (_loc_3 < _loc_5 && _loc_3 <= _local1)
                {
                    _loc_5 = _loc_3;
                    _loc_6 = _loc_4;
                }
                _loc_4++;
            }
            return _loc_6;
        }// end function

        public function findClosestLinePoint(points:Point, points:int) : Point
        {
            var _loc_3:Number = NaN;
            var _loc_4:Point = null;
            var _loc_5:Point = null;
            var _loc_6:* = Number.MAX_VALUE;
            var _loc_7:* = points * points;
            var _loc_8:* = Math.min(256, points.x + points);
            var _loc_9:* = Math.max(0, points.x - points);
            while (_loc_9 < _loc_8)
            {
                
                _loc_5 = new Point(_loc_9, this.splineVals[_loc_9]);
                _loc_3 = this.sqrEuclideanDistance2D(points, _loc_5);
                if (_loc_3 < _loc_6 && _loc_3 <= _loc_7)
                {
                    _loc_6 = _loc_3;
                    _loc_4 = _loc_5;
                }
                _loc_9++;
            }
            return _loc_4;
        }// end function

        public function movePoint(push:int, push:Point) : void
        {
            this.points[push] = push;
            return;
        }// end function

    }
}
